home *** CD-ROM | disk | FTP | other *** search
- #import "Celestial.h"
- #import "TiffManager.h"
- #import "Thinker.h"
- #import <appkit/NXBitmapImageRep.h>
- #define PI (3.141592653589)
- #define MAXMULTBODY 10 //total multiple objects allowed
-
- @implementation Celestial
-
- - init
- {
- [super init];
- tiffStorageIndex = 0;
- animationIndex = 0;
-
- tiffManagerObject = [[TiffManager alloc] init];
- tiffStorage = [tiffManagerObject returnTiffStorage];
-
- bodyList = [[List alloc] init];
-
- avoidStorage = [[Storage allocFromZone:[self zone]] initCount:0
- elementSize:sizeof(AvoidStruct) description:"{ffff}"];
-
- okToDoAnim = NO;
- currentBodyIndex = 0;
- cycleStartIndex = 0;
- cycles = 0;
- currentCycle = 1;
- bodyCount = 0;
- tiffsNeedBuilding = YES;
- okToDoAnim = NO;
- multDelay = floor(randBetween(objectSpeed * 0.1,
- (objectSpeed * 0.1) + 10));
- currentMultTotal = 1;
- [starsObject setStarsStopped];
- PSsetlinewidth(4.0); //0.0 is more efficient but I liked this better
-
- return self;
-
- }
- // Every module should have a first state method
- //since class info only gets loaded once - therefore only 1 init called
-
- - setFirstState
- {
- firstState = YES;
- okToDoAnim = NO;
- cycleStartIndex = currentBodyIndex;
-
- bodyCount = 0;
- tiffsNeedBuilding = YES;
- okToDoAnim = NO;
- multDelay = floor(randBetween(objectSpeed * 0.1,
- (objectSpeed * 0.1) + 10));
-
-
-
- currentMultTotal = 1;
- starsStopping = NO; //[starsObject isStopping]; //should be NO
- starsStopped = NO; //[starsObject isStopped]; //should be NO
-
- bodiesDone = 0;
- currentCycle = 1;
-
- return self;
- }
- - (BOOL)doUntilDone
- {
- BOOL done;
- int ii,count;
-
- done = NO;
-
- if(!starsStopping){
-
- if(!okToDoAnim){ //go build the tiffs
- if(tiffsNeedBuilding){
- tiffsNeedBuilding = [tiffManagerObject createTiffs];
- }
- else { //do the animation set up
- totalBodies = [tiffStorage count];
- animBuilt = (MAXANIMATIONS > totalBodies) ? totalBodies :
- MAXANIMATIONS; //pick smaller
- [self changeBodyList:currentBodyIndex];
- if(soundEnabled)
- [pwrUpSnd play];
- [starsObject startStars];
- starsStopping = NO; //[starsObject isStopping]; //should be NO
- starsStopped = NO; //[starsObject isStopped]; //should be NO
- okToDoAnim = YES;
- }
- } //now do the animation
- else {
- if(nextStartTime < 0){ //time to do animation
- count = [bodyList count];
- multDelay--;
- if(multDelay < 0){ // reset delay timer for next multiple object
- currentMultTotal++;
- if(currentMultTotal > count)
- currentMultTotal = count;
- multDelay = floor(randBetween(objectSpeed * 0.1,
- (objectSpeed * 0.1) + 10));
-
- }
- if(count){ // there are some objects to do
- for(ii = 0;ii < currentMultTotal;ii++){
- currentBody = [bodyList objectAt:ii];
- if([currentBody doUntilDone]){
- [bodyList removeObjectAt:ii];
- ii--;
- currentMultTotal--;
- currentBody = [currentBody free];
- }
- }
- [starsObject setAvoidRect:avoidStorage];//set avoidance for all
- //bodies
- }
- else { // object has zipped off screen
- //in case of multiple - last one has zipped off screen
- [self setNextStartTime];
- currentMultTotal = 1;
- multDelay = floor(randBetween(objectSpeed * 0.1,
- (objectSpeed * 0.1) + 10));
- bodyCount++;
- if(bodyCount >= animBuilt ){ //complete cycle is done
- currentCycle++;
- if(currentCycle > cycles){//done with this module
-
- if(!([starsObject isStopping])){
- if(soundEnabled)
- [pwrDownSnd play];
- [starsObject stopStars];
- starsStopping = YES;
- }
- currentBodyIndex++;
- if(currentBodyIndex >= totalBodies)
- currentBodyIndex = 0;
- cycleStartIndex = currentBodyIndex;
- }
- else {
- currentBodyIndex = cycleStartIndex;
- bodyCount = 0;
- [self changeBodyList:currentBodyIndex]; //create body
- }
- }
- else {
- currentBodyIndex++;
- if(currentBodyIndex >= totalBodies)
- currentBodyIndex = 0;
- [self changeBodyList:currentBodyIndex]; //create body
-
- }
- }
- }
- else
- nextStartTime--;
- }
- }
- else{ //stars are stopping
- if(starsStopped){
- PSsetlinewidth(0.0); //reset
- done = YES;
- }
- }
- return done;
- }
-
-
- - setStartInterval: (Slider *)sender;
- {
-
- startInterval = [sender intValue];
- nextStartTime = 0;
- return self;
-
- }
-
- - setNextStartTime
- {
- nextStartTime = startInterval;
- return self;
- }
- - setPwrDownSnd:(Sound *)theSound
- {
- pwrDownSnd = theSound;
- return self;
- }
- - setPwrUpSnd:(Sound *)theSound;
- {
- pwrUpSnd = theSound;
- return self;
- }
-
- - setObjectSpeed: (Slider *)sender
- {
-
- objectSpeed =([sender maxValue] + [sender minValue]) - [sender floatValue];
- return self;
- }
-
- - setBoundsRect:(NXRect *)r
- {
-
- bounds.origin.x = r->origin.x;
- bounds.origin.y = r->origin.y;
- bounds.size.width = r->size.width;
- bounds.size.height = r->size.height;
-
- return self;
- }
-
-
- - changeBodyList:(int)index
- {
-
- int ii;
- int total;
- AvoidStruct avoidStruct;
-
- for(ii=0;ii < 4;ii++) //init the lastTheta array
- lastTheta[ii] = -1;
-
- total = floor(randBetween(2,MAXMULTBODY));
-
- if([bodyList count]){
- [bodyList freeObjects];
- }
-
- [avoidStorage empty];
- isMult = ((ImageStruct *)[tiffStorage elementAt:
- index])->isMult;
-
- avoidStruct.avoid.origin.x = 0.0;
- avoidStruct.avoid.origin.y = 0.0;
- avoidStruct.avoid.size.width = 0.0;
- avoidStruct.avoid.size.height = 0.0;
-
- if(isMult){
- for(ii=0;ii < total;ii++){
- currentBody = [self createBody:index];
- [currentBody setBodyIndex:ii];
- [bodyList addObject:currentBody];
- [avoidStorage addElement:&avoidStruct];
- }
- }
- else{
- currentBody = [self createBody:currentBodyIndex];
- [bodyList addObject:currentBody];
- [avoidStorage addElement:&avoidStruct];
-
- }
-
- return self;
- }
-
-
- - (Body *)createBody:(int)index
- {
- Body *body;
- float theta; //angle of travel for new body
- float multObjectSpeed;
-
- body = [[Body alloc] init];
- [body setAvoidStorage:avoidStorage];
-
- [body setImageList:((ImageStruct *)[tiffStorage
- elementAt:index])->imageList];
-
- [body setNumberOfFrames];
- [body setBoundsRect:(NXRect *)&bounds]; //must be done after setCellSize
-
- if(isMult){
- multObjectSpeed = objectSpeed + floor(randBetween(0,10));
- [body setObjectSpeed:multObjectSpeed];
- theta = [self genUniqueTheta]; //make sure mult objects stay clear
- //of each other
-
- }
- else{
- [body setObjectSpeed:objectSpeed];
- theta = randBetween(0,(2*PI));
- }
- [body setAngle:theta];
- [body setStarsOutlet: (id)starsObject];
- return(body);
- }
-
- - starsStopped
- {
- starsStopped = YES;
- return self;
- }
- - setStarsOutlet:(id)starsOutlet;
- {
- starsObject = starsOutlet;
- return self;
- }// just a prototype - not used in this module
- - setStarSpeed:sender
- {
- return self;
- }
-
- //The idea here was that individual modules could decide
- //how to interpret the slider value
- // if you only want this module to do one pass etc.
-
- - (int)setCycleValue:(int)value;
- {
- int mutiplier;
- // since this module is interesting make it 5 times the slider value
- // could be zero
-
- mutiplier = 5;
- if(!value)
- value = 1;
- else
- value *= mutiplier;
- cycles = value;
- currentCycle = 1;
- return mutiplier;
- }
-
- - windowSizeChanged
- {
- if(currentBody){ //if one exists
-
- [self setNextStartTime];
- //[bodyList freeObjects];
- //printf("window size changed bodylist has %d elements\n",
- //[bodyList count]);
-
- currentMultTotal = 1;
- currentBody = nil;
- [self changeBodyList:currentBodyIndex];
- }
-
- return self;
- }
- - freeResources
- {
- [tiffManagerObject freeTiffs];
- if ([bodyList count]){
- [bodyList freeObjects];
- }
- return self;
- }
- // just a prototype - sound isn't used in this module
- - setSoundEnabled:(BOOL)enabled
- {
- soundEnabled = enabled;
- return self;
- }
-
- //for each 4 in a row - make sure random theta is
- // 40 degrees from any of the others
- - (float)genUniqueTheta
- {
- int ii;
- int maxTest = 4;
- float theta;
- BOOL thetaOK = NO;
-
- theta = randBetween(0,(2*PI));
-
- while(!thetaOK){
- thetaOK = YES;
- for(ii = 0;ii < maxTest;ii++){
- if(lastTheta[ii] < 0)
- continue;
- //.69 = 40 degrees
- if(theta > (lastTheta[ii] - .69) && theta < (lastTheta[ii] + .69)){
- thetaOK = NO;
- theta = randBetween(0,(2*PI));
- }
- }
- }
- for(ii = 1;ii < maxTest;ii++){
- lastTheta[ii-1] = lastTheta[ii];
- }
- lastTheta[ii-1] = theta;
-
-
-
- return theta;
- }
- @end
-